#include "Texture.h"

#include "Defines.h"

#if defined(__APPLE__) || defined(MACOSX)
	   #include <OpenGL/OpenGL.h>
	   #include <OpenGL/glu.h>
#endif
#if defined(_WIN32)
	#include <GL/gl.h>
	#include <GL/glu.h>
#endif

namespace Y{

bool Texture::use_mipmaps_default = true;



Texture::Texture(const char * pt, bool to_texture, bool keep){
	_init();
	load(pt);
	if ( to_texture ){
		toGLTexture(use_mipmaps_default,keep);
	}
}

Texture::Texture ( int w, int h ):
	width(w),
	height(h),
	fourHeight(h * 4)
{
	_init();
	image_data = new GLubyte[width * fourHeight];
}

Texture::Texture ( const Texture& t ){
	width = t.width;
	height = t.height;
	fourHeight = t.fourHeight;
	loaded = t.loaded;
	path = t.path;
	yID = t.yID;
	texID = t.texID;
	if ( t.image_data != NULL ){
		image_data = new GLubyte[width * fourHeight];
		for ( int i = 0; i < width * fourHeight; ++i ){
			image_data[i] = t.image_data[i];
		}
	}
	else{
		image_data = NULL;
	}
}

Texture& Texture::operator= ( const Texture& t ){
	width = t.width;
	height = t.height;
	fourHeight = t.fourHeight;
	loaded = t.loaded;
	path = t.path;
	yID = t.yID;
	texID = t.texID;
	if ( t.image_data != NULL ){
		image_data = new GLubyte[width * fourHeight];
		for ( int i = 0; i < width * fourHeight; ++i ){
			image_data[i] = t.image_data[i];
		}
	}
	else{
		image_data = NULL;
	}
	return *this;
}


Texture* Texture::protoLoadedTexture ( const char * pt ){
	Texture *t = new Texture();
	t->path = pt;
	return t;
}

Texture* Texture::mipmappedTexture ( const char * pt ){
	Texture * t = new Texture();
	t->load(pt);
	t->toGLTexture(true,false);
	return t;
}

void Texture::_init () {
	static int counter = 1;
	yID = counter;
	counter++;
}

void Texture::load (){
	load( path );
}

void Texture::load(const char* pt){
	
	path = pt;
	path.toOSPath();
	
	png::image < png::basic_rgba_pixel<GLubyte> > img( pt );
	width = img.get_width();
	height = img.get_height();
	fourHeight = width * 4;
	
	image_data = new GLubyte[width * fourHeight];
	int p = 0;
	for ( int j = 0; j < height; ++j ){
		for ( int i = 0; i < width; ++i ){
			int x = i;
			int y = height - j - 1;
			const typeof( img.get_pixel(x,y) ) & pix = img.get_pixel(x,y);
			image_data[p] =		pix.red;
			image_data[p + 1] = pix.green;
			image_data[p + 2] = pix.blue;
			image_data[p + 3] = pix.alpha;
			p += 4;
		}
	}
	
	loaded = true;
}






GLubyte& Texture::acc (int i, int j, int rgba){ return (image_data[j * fourHeight + i * 4 + rgba]); }

GLuint Texture::toGLTexture ( bool mipmap, bool keep ){
	glGenTextures(1,&texID);
	glBindTexture(GL_TEXTURE_2D,texID);
	
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	if ( mipmap ){
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);}
	else{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);}
	glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
	if ( mipmap ){	
		gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,width,height,GL_RGBA,GL_UNSIGNED_BYTE,image_data);}
	else{
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,image_data);}
	
	if ( ! keep ) { delete[] image_data;image_data = NULL; }
	
	return texID;
}

}
